#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <windows.h>



double GetTick(SYSTEMTIME *start, SYSTEMTIME *stop) {
	return stop->wHour * 3600  + stop->wMinute * 60  + stop->wSecond  + stop->wMilliseconds / 1000.0
		- (start->wHour * 3600 + start->wMinute * 60 + start->wSecond + start->wMilliseconds / 1000.0);
}

float inline InvSqrt(float x) {
	float xhalf = 0.5f*x;
	int i = *(int*)&x; // get bits for floating value
	i = 0x5f3759df - (i>>1); // gives initial guess y0
	x = *(float*)&i; // convert bits back to float
	x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
	return x;
}

double inline InvSqrt(double x) {
	double xhalf = 0.5f*x;
	__int64 i = *(__int64*)&x; // get bits for floating value
	i = 0x5fe6ec85e7de30da - (i>>1); // gives initial guess y0
	x = *(double*)&i; // convert bits back to float
	x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
	return x;
}



int main(int argc, char *argv[]) {
	const unsigned int Trials = 1000;
	const unsigned int Loops = 1000 * 1000;
	srand((unsigned int) time(0));
	SYSTEMTIME start;
	SYSTEMTIME stop;

	float frands[Trials];
	double drands[Trials];
	for (unsigned int i = 0; i < Trials; i++) {
		frands[i] = (float) (100 * rand() / (1.0 + RAND_MAX));
		drands[i] = frands[i];
	}

	printf("error: %e, %e\n", 
		abs(InvSqrt(frands[0]) - (float) (1.0f / sqrt(frands[0]))) * sqrt(frands[0]),
		abs(InvSqrt(drands[0]) - 1.0 / sqrt(drands[0])) * sqrt(drands[0]));

	double dtmp = 0;
	float ftmp = 0;

	GetLocalTime(&start);
	for (unsigned int i = 0; i < Trials; i++) {
		for (unsigned int j = 0; j < Loops; j++) {
			ftmp += InvSqrt(frands[i]);
		}
	}
	GetLocalTime(&stop);
	printf("Tick: %e\n", GetTick(&start, &stop));

	GetLocalTime(&start);
	for (unsigned int i = 0; i < Trials; i++) {
		for (unsigned int j = 0; j < Loops; j++) {
			dtmp += InvSqrt(drands[i]);
		}
	}
	GetLocalTime(&stop);
	printf("Tick: %e\n", GetTick(&start, &stop));

	GetLocalTime(&start);
	for (unsigned int i = 0; i < Trials; i++) {
		for (unsigned int j = 0; j < Loops; j++) {
			dtmp += 1.0 / sqrt(frands[i]);
		}
	}
	GetLocalTime(&stop);
	printf("Tick: %e\n", GetTick(&start, &stop));

	printf("Tmp: %e %e\n", ftmp, dtmp);
	getchar();

	return 0;
}